﻿global using MessageBox = HandyControl.Controls.MessageBox;
using System.Diagnostics;
using System.Text;
using System.Windows;
using MG.Repository;
using MG.Repository.Entity;
using MG.SmartHMI.Common;
using MG.SmartHMI.Entity.DAO;
using MG.Util.Log;

namespace MG.SmartHMI
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public static Autofac.IContainer Service { get; set; }

        public App()
        {
            this.Startup += App_Startup;

            // 非UI线程的未处理异常捕获
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            // UI线程未捕获异常处理事件
            DispatcherUnhandledException += App_DispatcherUnhandledException;
            // Task内未处理异常捕获
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;

            //注入
            Service = ModelLocator.ModelInjection();
        }

        private void App_Startup(object sender, StartupEventArgs e)
        {
            Process current = Process.GetCurrentProcess();
            Process[] processes = Process.GetProcessesByName(current.ProcessName);
            if (processes.Count() > 1)
            {
                HandyControl.Controls.MessageBox.Show("程序已运行,请勿重复打开！");
                this.Shutdown();
                return;
            }
            Task.Run(InitDatabase);
            EventBus.Default.Log(new LogInfo("启动软件"));
        }

        #region 异常处理

        /// <summary>
        /// 提取异常信息
        /// </summary>
        private static string ExceptionToString(Exception ex, string info)
        {
            StringBuilder str = new StringBuilder($"{DateTime.Now}, {info}发生了一个错误！{System.Environment.NewLine}");
            if (ex.InnerException == null)
            {
                str.Append($"【对象名称】：{ex.Source}{System.Environment.NewLine}");
                str.Append($"【异常类型】：{ex.GetType().Name}{System.Environment.NewLine}");
                str.Append($"【详细信息】：{ex.Message}{System.Environment.NewLine}");
                str.Append($"【堆栈调用】：{ex.StackTrace}");
            }
            else
            {
                str.Append($"【对象名称】：{ex.InnerException.Source}{System.Environment.NewLine}");
                str.Append($"【异常类型】：{ex.InnerException.GetType().Name}{System.Environment.NewLine}");
                str.Append($"【详细信息】：{ex.InnerException.Message}{System.Environment.NewLine}");
                str.Append($"【堆栈调用】：{ex.InnerException.StackTrace}");
            }
            return str.ToString();
        }

        /// <summary>
        /// Task线程内未捕获异常处理函数
        /// </summary>
        private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            try
            {
                if (e.Exception.GetType().Name.Equals("CylinderTimeoutException"))
                {
                    DispCylinderTimeoutException(e.Exception);
                    return;
                }

                string msg = ExceptionToString(e.Exception, "Task线程");
                EventBus.Default.Log(new LogInfo($"[Task线程] {msg}", LogLevel.Error));
                HandyControl.Controls.MessageBox.Show(msg, "系统错误", MessageBoxButton.OK, MessageBoxImage.Error);

                e.SetObserved();//设置该异常已察觉（这样处理后就不会引起程序崩溃）
            }
            catch (Exception ex)
            {
                string msg = ExceptionToString(ex, "Task线程处理函数");
                EventBus.Default.Log(new LogInfo($"[Task线程处理函数]  {msg}", LogLevel.Error));
                HandyControl.Controls.MessageBox.Show(msg, "系统错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void DispCylinderTimeoutException(Exception ex)
        {
            StringBuilder str = new StringBuilder($"{DateTime.Now}, 发生了一个错误！{System.Environment.NewLine}");
            str.Append($"【对象名称】：{ex.Source}{System.Environment.NewLine}");
            str.Append($"【异常类型】：{ex.GetType().Name}{System.Environment.NewLine}");
            str.Append($"【详细信息】：{ex.Message}{System.Environment.NewLine}");
            str.Append($"【堆栈调用】：{ex.StackTrace}");
            EventBus.Default.Log(new LogInfo($"{str}", LogLevel.Error));
            HandyControl.Controls.MessageBox.Show(ex.GetType().Name, "警告", MessageBoxButton.OK, MessageBoxImage.Error);
        }

        /// <summary>
        /// UI线程未捕获异常处理函数
        /// </summary>
        private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            try
            {
                if (e.Exception.GetType().Name.Equals("CylinderTimeoutException"))
                {
                    DispCylinderTimeoutException(e.Exception);
                    return;
                }

                e.Handled = true;
                string msg = ExceptionToString(e.Exception, "UI线程");
                EventBus.Default.Log(new LogInfo($"{msg}", LogLevel.Error));
                HandyControl.Controls.MessageBox.Show(msg, "系统错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            catch (Exception ex)
            {
                string msg = ExceptionToString(ex, "UI线程处理函数");
                EventBus.Default.Log(new LogInfo($"{msg}", LogLevel.Error));
                HandyControl.Controls.MessageBox.Show(msg, "系统错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// 非UI线程未捕获异常处理函数
        /// </summary>
        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                string msg;
                if (e.ExceptionObject is Exception ex)
                {
                    if (ex.GetType().Name.Equals("IOTimeoutException"))
                    {
                        DispCylinderTimeoutException(ex);
                        return;
                    }
                    msg = ExceptionToString(ex, "非UI线程");
                }
                else
                {
                    msg = $"发生了一个错误！信息:{e.ExceptionObject}";
                }
                EventBus.Default.Log(new LogInfo($"{msg}", LogLevel.Error));
                HandyControl.Controls.MessageBox.Show(msg, "系统错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            catch (Exception ex)
            {
                string msg = ExceptionToString(ex, "非UI线程处理函数");
                EventBus.Default.Log(new LogInfo($"{msg}", LogLevel.Error));
                HandyControl.Controls.MessageBox.Show(msg, "系统错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        #endregion 异常处理

        /// <summary>
        /// 检测数据库是否有对应数据，无则添加fakedata
        /// </summary>
        private void InitDatabase()
        {
            //初始化映射
            TinyMapHelper.InitMapper();

            RepositoryService<RegisterConfig>.Instance.InitDatabase(EntityHelper.Types);

            //添加监测地址
            var Maddress = RepositoryService<Config>.Instance.Query(t => t.Key.Equals("MonitoringAddress") && !t.IsDelete);
            if (Maddress == null || Maddress.Count < 1)
            {
                RepositoryService<Config>.Instance.Add(new Config() { Key = "MonitoringAddress", Value = "0" });
            }
            //添加软件名
            var apptitle = RepositoryService<Config>.Instance.Query(t => t.Key.Equals("AppTitle") && !t.IsDelete);
            if (apptitle == null || apptitle.Count < 1)
            {
                RepositoryService<Config>.Instance.Add(new Config() { Key = "AppTitle", Value = "MG.SmartHMI" });
            }

            //添加配方
            var listsln = RepositoryService<SlnConfig>.Instance.Query(t => !t.IsDelete);
            if (listsln == null || listsln.Count < 1)
            {
                RepositoryService<SlnConfig>.Instance.Add(new SlnConfig() { Name = "默认配方" });
                var defaultsln = RepositoryService<SlnConfig>.Instance.Query(t => !t.IsDelete).First();
                RepositoryService<Config>.Instance.Add(new Config() { Key = "LastSlnId", Value = defaultsln.Id.ToString() });
            }
        }
    }
}